package com.yn.common.exception;

import com.yn.common.util.R;
import java.util.stream.Collectors;
import javax.servlet.ServletException;
import javax.xml.bind.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebInputException;

/**
 * 全局异常捕获
 *
 * @author Bing
 * @version 1.0
 **/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler({BindException.class, MethodArgumentNotValidException.class,
      WebExchangeBindException.class})
  @ResponseStatus(code = HttpStatus.OK)
  public R<Object> handleException(BindException e) {
    String detail = ((BindingResult) e).getFieldErrors().stream()
        .map(err -> err.getField() + "[" + err.getDefaultMessage() + "]")
        .collect(Collectors.joining(";"));
    return R.of(HttpStatus.BAD_REQUEST.value(), detail);
  }

  @ExceptionHandler({ValidationException.class,
      ServerWebInputException.class,
      ServletRequestBindingException.class,
      HttpMessageConversionException.class,
      ServletException.class})
  @ResponseStatus(code = HttpStatus.OK)
  public R<Object> handleInputException(Exception e) {
    return R.of(HttpStatus.BAD_REQUEST.value(), e.getLocalizedMessage());
  }

  /**
   * 业务异常
   *
   * @param e
   * @return
   */
  @ExceptionHandler(BizException.class)
  @ResponseStatus(code = HttpStatus.OK)
  public R<Object> handleException(BizException e) {
    return R.of(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getLocalizedMessage());
  }

  /**
   * 其他异常
   *
   * @param e
   * @return
   */
  @ExceptionHandler(Exception.class)
  @ResponseStatus(code = HttpStatus.OK)
  public R<Object> handleException(Exception e) {
    if (log.isErrorEnabled()) {
      log.error("全局捕获未知异常", e);
    }
    return R.of(HttpStatus.INTERNAL_SERVER_ERROR.value(), "操作失败，请联系系统管理员或请稍后再试");
  }
}
